package com.wgzx.modbus.client;

import com.wgzx.modbus.constant.ModbusConstants;
import com.wgzx.modbus.factory.CodecFactory;
import com.wgzx.modbus.factory.ModbusCodecFactory;
import com.wgzx.modbus.idgen.AtomicIdentifierGenerator;
import com.wgzx.modbus.idgen.IdentifierGenerator;
import com.wgzx.modbus.message.DefaultMsgManager;
import com.wgzx.modbus.message.MsgManager;
import com.wgzx.modbus.util.ModbusUtil;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;

public final class ModbusClientBuilder {

    private String host;
    private int port = ModbusConstants.DEFAULT_MODBUS_PORT;
    private EventLoopGroup eventLoopGroup;
    private int connectTimeoutMillis = 5000;
    private int retryIntervalMillis = 5000;
    private int protocolIdentifier = ModbusConstants.DEFAULT_PROTOCOL_IDENTIFIER;
    private short unitIdentifier = ModbusConstants.DEFAULT_UNIT_IDENTIFIER;
    private boolean enableLog = false;
    private CodecFactory codecFactory;
    private MsgManager msgManager;
    private IdentifierGenerator identifierGenerator;

    private ModbusClientBuilder() {}

    public static ModbusClientBuilder newBuilder() {
        return new ModbusClientBuilder();
    }

    public ModbusClient build() {
        if(this.identifierGenerator == null) {
            this.identifierGenerator = new AtomicIdentifierGenerator();
        }

        if(this.codecFactory == null) {
            this.codecFactory = ModbusCodecFactory.INSTANCE;
        }

        if(this.eventLoopGroup == null) {
            this.eventLoopGroup = new NioEventLoopGroup(1);
        }

        if(this.msgManager == null) {
            this.msgManager = new DefaultMsgManager();
        }

        ModbusUtil.validateNonNull(host, "host");

        return new ModbusClient(host, port, eventLoopGroup, enableLog, connectTimeoutMillis, retryIntervalMillis,
                protocolIdentifier, unitIdentifier, codecFactory, msgManager, identifierGenerator);
    }

    public ModbusClientBuilder setHost(String host) {
        this.host = host;
        return this;
    }

    public ModbusClientBuilder setPort(int port) {
        ModbusUtil.validateNonNegative(port, "port");
        this.port = port;
        return this;
    }

    public ModbusClientBuilder setEventLoopGroup(EventLoopGroup eventLoopGroup) {
        this.eventLoopGroup = eventLoopGroup;
        return this;
    }

    public ModbusClientBuilder setConnectTimeoutMillis(int connectTimeoutMillis) {
        ModbusUtil.validateNonNegative(connectTimeoutMillis, "connectTimeoutMillis");
        this.connectTimeoutMillis = connectTimeoutMillis;
        return this;
    }

    public ModbusClientBuilder setRetryIntervalMillis(int retryIntervalMillis) {
        ModbusUtil.validateNonNegative(retryIntervalMillis, "retryIntervalMillis");
        this.retryIntervalMillis = retryIntervalMillis;
        return this;
    }

    public ModbusClientBuilder setProtocolIdentifier(int protocolIdentifier) {
        this.protocolIdentifier = protocolIdentifier;
        return this;
    }

    public ModbusClientBuilder setUnitIdentifier(short unitIdentifier) {
        this.unitIdentifier = unitIdentifier;
        return this;
    }

    public ModbusClientBuilder setEnableLog(boolean enableLog) {
        this.enableLog = enableLog;
        return this;
    }

    public ModbusClientBuilder setCodecFactory(CodecFactory codecFactory) {
        this.codecFactory = codecFactory;
        return this;
    }

    public ModbusClientBuilder setMsgManager(MsgManager msgManager) {
        this.msgManager = msgManager;
        return this;
    }

    public ModbusClientBuilder setIdentifierGenerator(IdentifierGenerator identifierGenerator) {
        this.identifierGenerator = identifierGenerator;
        return this;
    }

}
